2023.6.1 自動微分について【torch】
PyTorchのテンソル型オブジェクトは自動微分とよばれる処理を実装している。これはプログラムの実行によって行われた一連の計算過程についての勾配を求めるためのアルゴリズムである。
$ y = x^2という計算において、勾配$ \left. \frac{\partial y}{\partial x} \right|_{x=1}を求めましょう。
code:python
import torch
x = torch.tensor(1, dtype=torch.float, requires_grad=True) #(1) (1)で、テンソル型の変数xを次のように定義します。
値「1」を代入
データ型はtorch.foat
requires_grad=Trueとすることで、変数xをリーフノード(独立変数)に設定する。これで後で実行する従属変数に対する自動微分により、xには勾配を格納することができるようになる。
(2)で計算を行います。この際、リーフノードである独立変数$ xから従属変数$ yに到るまでの計算過程をグラフ化した「計算グラフ」が生成される。
(3)で$ yに対して自動微分を適用すると、計算グラフをもとに勾配を計算し、リーフノードのインスタンス変数gradに格納する。
$ \left. \frac{\partial y}{\partial x} \right|_{x=1}= \left. \frac{\partial x^2}{\partial x}\right|_{x=1} =\left. 2x\right|_{x=1} = 2
(4)で確認しています。
可視化して確認してみましょう。
code:python
import torch
import matplotlib.pyplot as plt
import numpy
x = torch.tensor(1, dtype=torch.float, requires_grad=True) #(1) xs = numpy.linspace(-3, 3, 30)
ys1 = xs**2
b = 1 - x.grad*1 # (1,1)を通る傾きx.gradの直線のy切片
ys2 = x.grad*xs + b
plt.plot(xs, ys1)
plt.plot(xs, ys2)
plt.xlim(-1, 2)
plt.ylim(-1, 3)
plt.grid()
plt.show()
https://scrapbox.io/files/646eaecdaea626001b5f8e31.png
となり、確かにx=1における傾きがx.gradに格納されています。
ユーザ関数で定義した計算の結果についての勾配を求めることもできます。
code:python
import torch
def f(x):
return x**2
x1 = torch.tensor(1, dtype=torch.float, requires_grad=True) # (1)
y = f(x1) # (2)
y.backward() # (3)
print(x1.grad) # (4)
また、PyTorchが提供する関数は自動微分に対応しています。NumPyの関数に勾配属性を持たせた(requires_grad=Trueな)テンソルを与えることはできません。(対応表) テンソル型オブジェクトが保持する値へのアクセスには変数名を利用しまが、これでは値そのものと勾配の区別が付かないので、値に対してはdata、勾配に対してはgrad属性を利用します。
code:pyton
# 上のサンプルに続き
print(x.data)
print(x.grad)